package com.timzer.module.console;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;

@ServerEndpoint("/imserver/{userId}")
@Component
@Slf4j
public class WebSocketServer {

    boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
    /**静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。*/
    private static int onlineCount = 0;
    /**concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。*/
    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    /**与某个客户端的连接会话，需要通过它来给客户端发送数据*/
    private Session session;
    /**接收userId*/
    private String userId="";
    private StringBuffer cmdStrB = new StringBuffer();

    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session,@PathParam("userId") String userId) {
        this.session = session;
        this.userId=userId;
        if(webSocketMap.containsKey(userId)){
            webSocketMap.remove(userId);
            webSocketMap.put(userId,this);
            //加入set中
        }else{
            webSocketMap.put(userId,this);
            //加入set中
            addOnlineCount();
            //在线数加1
        }

        log.info("用户连接:"+userId+",当前在线人数为:" + getOnlineCount());

        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("用户:"+userId+",网络异常!!!!!!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(webSocketMap.containsKey(userId)){
            webSocketMap.remove(userId);
            //从set中删除
            subOnlineCount();
        }
        log.info("用户退出:"+userId+",当前在线人数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {

        if("\u007F".equals(message)){
            if(cmdStrB.length()>0) {
                message = "\b\u007F";
                cmdStrB.delete(cmdStrB.length() - 1, cmdStrB.length());
            }else {
                message = "";
            }
        }else {
            cmdStrB.append(message);
        }
        System.out.println(cmdStrB);
        String msg = message.replace("\r","\r\n");
        webSocketMap.get("id").sendMessage(msg);
        //可以群发消息
        //消息保存到数据库、redis
        if("\t".equals(message) || "\r".equals(message)){
            Process process;
            InputStream inputStream;
            BufferedReader reader;
            String shell = cmdStrB.toString().replaceAll("__", "/");
            if (isWindows) {
                process = Runtime.getRuntime().exec(String.format("cmd.exe /c %s", shell));
            } else {
                String[] cmd = {"/bin/sh","-c",shell};
                process = Runtime.getRuntime().exec(String.format("sh -c %s", shell));
//                String commond = shell.replaceAll("__", "/");
//                process = Runtime.getRuntime().exec(cmd);
            }
            inputStream = process.getInputStream();
            if(inputStream.read()==-1){
                inputStream = process.getErrorStream();
            }
            reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while(null != (line = reader.readLine())){
//                session.getBasicRemote().sendText(line + "<br>");
                System.out.println(line);
                webSocketMap.get("id").sendMessage(line+"\r\n");
            }
            if("\r".equals(message)){
                cmdStrB.delete(0,cmdStrB.length());
                webSocketMap.get("id").sendMessage("[shell/exec:~]$");
                process.destroy();
            }
        }
    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:"+this.userId+",原因:"+error.getMessage());
        error.printStackTrace();
    }
    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * 发送自定义消息
     * */
    public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException {
        log.info("发送消息到:"+userId+"，报文:"+message);
        if(StringUtils.isNotBlank(userId)&&webSocketMap.containsKey(userId)){
            webSocketMap.get(userId).sendMessage(message);
        }else{
            log.error("用户"+userId+",不在线！");
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

    public static void main(String[] args) throws IOException {
        boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
        Process process;
        InputStream inputStream;
        BufferedReader reader;
        Scanner sc = new Scanner(System.in);

        while (sc.hasNext()){
            String shell = sc.next();
            if (isWindows) {
                process = Runtime.getRuntime().exec(String.format("cmd.exe /c %s", shell));
            } else {
                process = Runtime.getRuntime().exec(String.format("sh -c '%s'", shell));
            }
            inputStream = process.getInputStream();
            if(inputStream.read()==-1){
                inputStream = process.getErrorStream();
            }
            reader = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while(null != (line = reader.readLine())){
//                session.getBasicRemote().sendText(line + "<br>");
                System.out.println(line);
            }
//            int exitCode = process.waitFor();

        }
    }

    public static void replace(){

    }
}
